package net.wanglu.www.zzz.rule.sva;

import java.util.HashMap;

import net.wanglu.www.zzz.rule.BadEgg;
import net.wanglu.www.zzz.rule.Rule;
import net.wanglu.www.zzz.service.se.nsubj._NSubjTuple;
import edu.stanford.nlp.ling.TaggedWord;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.trees.TreeGraphNode;
import edu.stanford.nlp.trees.tregex.TregexPattern;

public class MoreMostHalfEnoughPlentyAsSubj extends _SvaRule {

	public static final TregexPattern More = TregexPattern.compile("/\\bNP\\b/<:(/\\bJJR\\b/</\\bMore\\b/)");
	public static final TregexPattern MoreOfNN = TregexPattern.compile("/\\bNP\\b/<(/\\bNP\\b/<(/\\bJJR\\b</\\bMore\\b/))<(/\\bPP\\b/<(/\\bIN\\b/</\\bof\\b/)<(/\\bNP\\b/</\\bNN\\b/))");
	public static final TregexPattern MoreOfNNS = TregexPattern.compile("/\\bNP\\b/<(/\\bNP\\b/<(/\\bJJR\\b</\\bMore\\b/))<(/\\bPP\\b/<(/\\bIN\\b/</\\bof\\b/)<(/\\bNP\\b/</\\bNNS\\b/))");
	public static final TregexPattern MoreOfPRP = TregexPattern.compile("/\\bNP\\b/<(/\\bNP\\b/<(/\\bJJR\\b</\\bMore\\b/))<(/\\bPP\\b/<(/\\bIN\\b/</\\bof\\b/)<(/\\bNP\\b/</\\bPRP\\b/))");
	public static final TregexPattern HalfOfNN = TregexPattern.compile("/\\bNP\\b/<(/\\bNP\\b/<(/\\bQP\\b/<(/\\bDT\\b/</\\bHalf\\b/)))<(/\\bPP\\b/<(/\\bIN\\b/</\\bof\\b/)<(/\\bNP\\b/</\\bNN\\b/))");
	public static final TregexPattern HalfOfNNS = TregexPattern.compile("/\\bNP\\b/<(/\\bNP\\b/<(/\\bQP\\b/<(/\\bDT\\b/</\\bHalf\\b/)))<(/\\bPP\\b/<(/\\bIN\\b/</\\bof\\b/)<(/\\bNP\\b/</\\bNNS\\b/))");
	public static final TregexPattern Enough = TregexPattern.compile("/\\bNP\\b/<:(/\\bNNP\\b/</\\bEnough\\b/)");
	public static final TregexPattern EnoughOfNN = TregexPattern.compile("/\\bNP\\b/<</\\b[Ee]nough\\b/<(/\\bPP\\b/<(/\\bIN\\b/</\\bof\\b/)<(/\\bNP\\b/</\\bNN\\b/))");
	public static final TregexPattern EnoughOfNNS = TregexPattern.compile("/\\bNP\\b/<</\\b[Ee]nough\\b/<(/\\bPP\\b/<(/\\bIN\\b/</\\bof\\b/)<(/\\bNP\\b/</\\bNNS\\b/))");
	public static final TregexPattern PlentyOfNN = TregexPattern.compile("/\\bNP\\b/<(/\\bNP\\b/</\\bRB\\b/</\\bplenty\\b/)<(/\\bPP\\b<(/\\bIN\\b/</\\bof\\b/)<(/\\bNP\\b/</\\bNN\\b/))");
	public static final TregexPattern PlentyOfNNS = TregexPattern.compile("/\\bNP\\b/<(/\\bNP\\b/</\\bRB\\b/</\\bplenty\\b/)<(/\\bPP\\b<(/\\bIN\\b/</\\bof\\b/)<(/\\bNP\\b/</\\bNNS\\b/))");
	public static final TregexPattern TheMost = TregexPattern.compile("/\\bNP\\b/<(/\\bDT\\b/</\\bThe\\b/)<(/\\bJJS\\b/</\\bmost\\b/)");

	@Override
	public Object applicable(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		if ( super.applicable(objects) == Rule.Inapplicable) return Rule.Inapplicable;
		_NSubjTuple nst = (_NSubjTuple) objects[1];
		if ( !"NP".equals(nst.getSubjectAncestor().value())) return Rule.Inapplicable;
		return Rule.Applicable;
	}

	@Override
	public Object deviseRightSolution(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object examine(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		HashMap<?, ?> preprocessData = (HashMap<?, ?>) objects[0];
		_NSubjTuple nst =  (_NSubjTuple) objects[1];
		
		if ( this.applicable(preprocessData, nst) == Rule.Inapplicable) return Rule.Inapplicable;
		TreeGraphNode subj = (TreeGraphNode) nst.getSubj();
		TreeGraphNode verb = (TreeGraphNode) nst.getVerb();
		TreeGraphNode cop = (TreeGraphNode) nst.getCop();
		TreeGraphNode closestAux = (TreeGraphNode) nst.getAux();
		Tree subjAncestor = nst.getSubjectAncestor();
		
		TreeGraphNode pred = verb;
		if ( cop != null) pred = cop;
		if ( closestAux != null) pred = closestAux;
		String predWord = pred.label().word();
		String predTag = pred.label().tag();

		sb.clear();
		for( TaggedWord tw : subjAncestor.taggedYield()) {
			sb.append(tw.word()).append(" ");
		}
		
		if ( MoreMostHalfEnoughPlentyAsSubj.More.matcher(subjAncestor).find()) {
			if (Rule.SingularVerb.matcher(predTag).find() && !"were".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}			
		} else if ( MoreMostHalfEnoughPlentyAsSubj.MoreOfNN.matcher(subjAncestor).find()) {
			if (Rule.SingularVerb.matcher(predTag).find() && !"were".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}						
		} else if ( MoreMostHalfEnoughPlentyAsSubj.MoreOfNNS.matcher(subjAncestor).find()) {
			if (Rule.PluralVerb.matcher(predTag).find() && !"was".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}											
		} else if ( MoreMostHalfEnoughPlentyAsSubj.MoreOfPRP.matcher(subjAncestor).find()) {
			if (Rule.PluralVerb.matcher(predTag).find() && !"was".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}
		} else if ( MoreMostHalfEnoughPlentyAsSubj.HalfOfNN.matcher(subjAncestor).find()) {
			if (Rule.SingularVerb.matcher(predTag).find() && !"were".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}						
		} else if ( MoreMostHalfEnoughPlentyAsSubj.HalfOfNNS.matcher(subjAncestor).find()) {
			if (Rule.PluralVerb.matcher(predTag).find() && !"was".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}
		} else if ( MoreMostHalfEnoughPlentyAsSubj.Enough.matcher(subjAncestor).find()) {
			if (Rule.SingularVerb.matcher(predTag).find() && !"were".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}						
		} else if ( MoreMostHalfEnoughPlentyAsSubj.EnoughOfNN.matcher(subjAncestor).find()) {
			if (Rule.SingularVerb.matcher(predTag).find() && !"were".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}						
		} else if ( MoreMostHalfEnoughPlentyAsSubj.EnoughOfNNS.matcher(subjAncestor).find()) {
			if (Rule.PluralVerb.matcher(predTag).find() && !"was".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}
		} else if ( MoreMostHalfEnoughPlentyAsSubj.PlentyOfNN.matcher(subjAncestor).find()) {
			if (Rule.SingularVerb.matcher(predTag).find() && !"were".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}						
		} else if ( MoreMostHalfEnoughPlentyAsSubj.PlentyOfNNS.matcher(subjAncestor).find()) {
			if (Rule.PluralVerb.matcher(predTag).find() && !"was".equals(predWord)) {
				return null;
			} else {
				BadEgg egg = new BadEgg();
				egg.setProperty(BadEgg.Error);
				egg.setViolatedRule(this);
				egg.whereIsWrong = nst;
				return egg;
			}
		} else if ( MoreMostHalfEnoughPlentyAsSubj.TheMost.matcher(subjAncestor).find()) {
			BadEgg egg = new BadEgg();
			egg.setProperty(BadEgg.Warning);
			egg.setViolatedRule(this);
			egg.whereIsWrong = nst;
			return egg;
		}
		return Rule.Inapplicable;
	}
	@Override
	public Object whyItsWrong(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		sb.clear();
		sb.append("<p>");
		sb.append("当more，most，half，enough，plenty等作主语时，其主谓一致关系遵循意义一致原则，如果所指为复数意义，谓语动词用复数形式。如果所指为单数意义，谓语动词则用单数形式。");
		sb.append("</p>");
		return sb.toString();
	}
}
